/**
 * 控制配置
 */
import fs from 'fs';
import path from 'path'
import loader from '../core/loader';
import sugar from '../core/sugar';
import controRoute from '../route/RouterHandler';
import Ioc from '../core/Ioc';
import Config from '../model/Config';
import Out from '../utils/Out';
import ErrorUtils from '../utils/ErrorUtils';

const baseConfig = process.cwd()+"/cgem.config.json"


class ConfigHandler {
    /** 配置数据 */
    public static configData:Config;

    /** 初始化配置文件以及加载器 */
    static {
      // 初始化实例
      this.configData = new Config();
      if(fs.existsSync(process.cwd()+baseConfig)){
        // 导入配置文件并且初始化
        this.setConfig(require(process.cwd()+baseConfig))
      }
      // 配置加载成功
      Out.success("配置加载成功");
      // 初始化加载器
      global.loader = loader.createLoader(ConfigHandler.configData?.modules || {});
      // 加载器加载成功
      Out.success("加载器初始化成功");
    }
    
    // 添加扩展 扩展必须是可直接使用的方法
    static addPlug(id:Function|any):void{
        ConfigHandler.configData.plug.push(id.default || id)
    }
    // 获取扩展
    static getPlug():Array<controllerStructure>{
        return ConfigHandler.configData.plug;
    }
    // 设置扩展
    static setPlug(data:Array<controllerStructure>){
        ConfigHandler.configData.plug = data;
    }
    // 返回配置文件
    static getConfig():config{
        return ConfigHandler.configData;
    }

    // 获取启动服务配置
    static getServers():{host:string,port:number};
    static getServers(id:string):{host:string,port:number}|string|number|Function;
    static getServers(id?:string):{host:string,port:number}|string|number|Function{
        if(id !== undefined) return ConfigHandler.configData.server[id];
        return ConfigHandler.configData.server;
    }

    // 获取特性信息
    static getFeatures():Record<string,boolean>;
    static getFeatures(id:string):boolean;
    static getFeatures(id?:string):any{
        if(id !== undefined) return ConfigHandler.configData.features[id]
        return ConfigHandler.configData.features;
    }

    // 获取全局模块
    static getModules():Record<string,string>{
        return ConfigHandler.configData.modules;
    }

    // 获取中间件
    static getMiddleware(id:string):string;
    static getMiddleware():Record<string,string>;
    static getMiddleware(id?:string):Record<string,string>|string{
        if(id !== undefined) return ConfigHandler.configData.middleware[id];
        return ConfigHandler.configData.middleware;
    }

    // 获取全局中间件
    static getGlobal_Middleware():Array<string|Function>{
        return ConfigHandler.configData.global_middleware;
    }

    // 获取注解配置
    static getAnnotation(id:string):string;
    static getAnnotation():Record<string,string>;
    static getAnnotation(id?:string):Record<string,string>|string{
        if(id !== undefined) return ConfigHandler.configData.annotation[id];
        return ConfigHandler.configData.annotation;
    }

    // 获取地址
    static getAddress(id?:string):string|Record<string,string>|any{
        if(id !== undefined) return ConfigHandler.configData.address[id];
        return ConfigHandler.configData.address;
    }

    // 获取运行注解的地址
    static getrunAnnotation():Array<string>{
        return ConfigHandler.configData.runAnnotation;
    }

    // 获取路由文件的配置
    static getRouteConfig():Array<routeFile>;
    static getRouteConfig(id:string):routeFile;
    static getRouteConfig(id?:string):Array<routeFile>|routeFile{
        if(id !== undefined)
        return ConfigHandler.configData.routeConfig[id]
        return ConfigHandler.configData.routeConfig;
    }

    // 获取特殊接口的配置
    static getSpecial(id?:string):specialInter|Record<string,specialInter>{
        if(id !== undefined) return ConfigHandler.configData.special[id];
        return ConfigHandler.configData.special;
    }

    // 获取语法糖
    static getpathSugar(id:string) :string;
    static getpathSugar() :Record<string,string>;
    static getpathSugar(id?:string) :string|Record<string,string>{
        if(id !== undefined) return ConfigHandler.configData.pathSugar[id];
        return ConfigHandler.configData.pathSugar;
    }

    //===============================================================

    // 设置配置文件
    static setConfig(config:Config):void{
      // 注解合并
      config.annotation = Object.assign(this.configData.annotation,config.annotation || {});
      // 地址合并
      config.address    = Object.assign(this.configData.address,config.address || {});
      // 特殊的路由接口合并
      config.special    = Object.assign(this.configData.special,config.special || {})
      // 语法糖合并
      config.pathSugar  = Object.assign(this.configData.pathSugar,config.pathSugar || {})
      // 初始化一下
      Object.keys(config).forEach(e=>{
        if(config[e] != undefined)
        ConfigHandler.configData[e] = config[e];
      })
      ConfigHandler.configData = config;
    }

    // 设置启动服务配置
    static setServers(id:string|{host:string,port:number},v?:string|any):void{
        if(typeof id === 'object')
            ConfigHandler.configData.server = id;
        else
            ConfigHandler.configData.server[id] = v;
    }

    // 设置特性信息
    static setFeatures(id:string,v:string):void{
        ConfigHandler.configData.features[id] = v;
    }

    // 添加全局模块
    static addModules(id:string,v:string):void{
        ConfigHandler.configData.modules[id] = sugar.path(path.join(v),{superNumber:3});
    }

    // 添加中间件
    static addMiddleware(id:string,v:string):void{
      if(typeof v === 'string'){
        this.configData.middleware[id]=v;
        return
      }
      ErrorUtils.error("路径类型错误，只接受string文件路径");
    }

    // 添加全局中间件
    static addGlobal_Middleware(v:string):void{
        if(typeof v === "string"){
          ConfigHandler.configData.global_middleware.push(v);
          return;
        }
        ErrorUtils.error("路径类型错误，只接受string文件路径");
    }

    // 添加注解配置
    static addAnnotation(id:string,v:string|any):void{
        if(typeof v === "string")v = path.join(v);
        ConfigHandler.configData.annotation[id] = v;
    }

    // 添加地址
    static addAddress(id:string,v:string):void{
        ConfigHandler.configData.address[id] = path.join(v);
    }

    // 添加运行注解的地址
    static addrunAnnotation(v:string):void{
        ConfigHandler.configData.runAnnotation.push(path.join(v));
    }

    // 添加路由文件的配置
    static addrouteConfig(v:routeFile):void{
        v.path =path.join(v.path);
        ConfigHandler.configData.routeConfig.push(v);
    }

    // 添加特殊接口的配置
    static addSpecial(id:string,v:specialInter):void{
        v.path = path.join(v.path);
        ConfigHandler.configData.special[id] = v;
    }

    // 添加语法糖
    static addpathSugar(id:string,v:string):void{
        ConfigHandler.configData.pathSugar[id] = v;
    }


    static init(middleware:any){
      // 初始化路由文件
      for(let e of ConfigHandler.getRouteConfig()){
          e.prefix || (e.prefix="")
          e.middleware || (e.middleware = [])
          if(!e.path){
              throw new Error("路由文件路径没有配置")
          }
      }
      Out.success("路由初始化成功")

      // 初始化ioc (也就是modules)
      let moduless = ConfigHandler.getModules();
      for(let e in moduless){
          moduless[e] = sugar.path(moduless[e],{pathSugar:ConfigHandler.getpathSugar()})
          // 把模块解析出来存放到Ioc容器中
          Ioc.add(e,moduless[e])
      }
      Out.success("IOC 初始化成功")

      // 初始化中间件
      let Middlware = ConfigHandler.getMiddleware()
      let middDir = ConfigHandler.getAddress("middleware");
      middDir?(middDir+="/"):(middDir = "")
      for(let e in Middlware){
          if(!/^\/|^[A-Z]:/.test(Middlware[e])){
              // 这不是绝对路径，完善路径
              Middlware[e] = sugar.path(path.join(middDir + Middlware[e]));
          }
          // 把中间件解析出来存放到中间件池中
          controRoute.addMiddleware(e,middleware.auto_pars(Middlware[e],e))
      }
      Out.success("中间件初始化成功")


      // 初始化注解  这里可有可无，提前初始化相当与提前缓存
      let annotation = ConfigHandler.getAnnotation();
      for(let e in annotation){
          // 判断一下注解的地址
          if(typeof annotation[e] === "string" && !/^[./\\]|^[A-Z]\:/.test(annotation[e])){
              // 如果文件不存在说明是第三方模块
              if(fs.existsSync( ConfigHandler.getAddress("annotation") + "/" + annotation[e])){
                  annotation[e] = ConfigHandler.getAddress("annotation") +"/"+ annotation[e];
              }
              // 添加到IOC容器中
              Ioc.add(e,annotation[e])
          }
      }
      Out.success("注解初始化成功")

    }
}
// 初始化模块加载器
if(global.loader == undefined)
global.loader = ()=>console.log("加载器尚未初始化")

export = ConfigHandler;
